/*
 * Copyright Notice ====================================================
 * This file contains proprietary information of JeeStrap Co.
 * Copying or reproduction without prior written approval is prohibited.
 * Copyright (c) 2014 All rights reserved. =============================
 */

package com.jeestrap.common.smartcoder.gui.codeview;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import com.jeestrap.common.smartcoder.database.DbUtil;
import com.jeestrap.common.smartcoder.domain.CodeDesc;
import com.jeestrap.common.smartcoder.gui.setting.SettingFrame;
import com.jeestrap.common.smartcoder.util.AppUtil;
import com.jeestrap.common.smartcoder.util.Constants;
import com.jeestrap.common.smartcoder.util.FileUtils;
import com.jeestrap.common.smartcoder.util.StrUtils;
import com.jeestrap.common.smartcoder.util.ZipUtil;

public class CodeViewFrame extends JFrame implements ActionListener {

	/**
	 * serialVersionUID long
	 */
	private static final long serialVersionUID = 1182685843281787021L;

	private JPanel naviPanel;

	private JSplitPane codeViewPanel;

	private JPanel btnPanel;

	private JLabel settingNaviLabel;

	private JButton returnButton;

	private JButton saveButton;

	private CodeDesc codeDesc;

	JTree tree;

	JScrollPane codeScrollPane;

	JEditorPane srcTextArea = new JEditorPane();

	Map<String, String> genCodeMap;

	private String selectedFileName;

	SettingFrame frame;

	/**
	 * Create the frame.
	 */
	public CodeViewFrame(SettingFrame frame, CodeDesc codeDesc, Map<String, String> genCodeMap) {
		this.codeDesc = codeDesc;
		this.frame = frame;
		this.genCodeMap = genCodeMap;

		Dimension localDimension = Toolkit.getDefaultToolkit().getScreenSize();
		// int width = (int)(localDimension.getWidth()-100);
		// int height = (int)(localDimension.getHeight()-100);
		int width = 900;
		int height = 600;
		// this.setSize((int)localDimension.getWidth(), (int)localDimension.getHeight());
		this.setBounds(0, 0, width, height);
		this.setSize(width, height);
		setLocation((int)(localDimension.getWidth() - getWidth()) / 2,
			(int)(localDimension.getHeight() - getHeight()) / 2);

		// 设置框架窗体的事件监听(关闭窗体事件)
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				DbUtil.realseConnection();
				System.exit(0);
			}
		});

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("JeeWeb - 代码生成器");

		setIconImage(new ImageIcon(ClassLoader.getSystemResource("logo.png")).getImage());

		createNaviPane();
		createCodeViewPane();
		createBtnPane();

		getContentPane().add("North", naviPanel);
		getContentPane().add("Center", codeViewPanel);
		getContentPane().add("South", btnPanel);
	}

	/**
	 * 下面是导航面板的创建过程
	 * 
	 * @return
	 * 
	 * @since
	 */
	private JPanel createNaviPane() {
		naviPanel = new JPanel();
		settingNaviLabel = new JLabel("预览修改并保存代码");
		// 把四个功能按钮加入功能按钮面板中
		naviPanel.add(settingNaviLabel);
		return naviPanel;
	}

	/**
	 * 下面是设置面板的创建过程
	 * 
	 * @return
	 * 
	 * @since
	 */
	private JSplitPane createCodeViewPane() {
		codeViewPanel = new JSplitPane();

		JScrollPane codeTreePanel = new JScrollPane();
		codeTreePanel.setToolTipText("代码目录结构");
		initTree();
		tree.addTreeSelectionListener(new TreeSelectionListener() {
			public void valueChanged(TreeSelectionEvent e) {
				srcTextArea.setText("");
				TreePath treePath = tree.getSelectionModel().getSelectionPath();// 返回最后选定的节点
				selectedFileName = StrUtils.join(treePath.getPath(), "\\");
				srcTextArea.setText(CodeViewUtil.loadSourceCode(genCodeMap.get(selectedFileName)));
				codeScrollPane.setToolTipText(selectedFileName);
			}
		});
		codeTreePanel.getViewport().add(tree);

		codeViewPanel.setLeftComponent(codeTreePanel);

		codeScrollPane = new JScrollPane();
		srcTextArea.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent e) {
				Document doc = srcTextArea.getDocument();
				String text = "";
				try {
					text = doc.getText(0, doc.getLength());
				} catch (BadLocationException e1) {
					System.out.println(e1.getMessage());
				}
				genCodeMap.put(selectedFileName, text);

			}
		});
		srcTextArea.setText("");
		srcTextArea.setContentType("text/html");
		codeScrollPane.getViewport().add(srcTextArea);

		codeViewPanel.setRightComponent(codeScrollPane);

		codeViewPanel.setDividerLocation(300);
		codeViewPanel.setDividerSize(8);
		codeViewPanel.setOneTouchExpandable(true);
		// codeViewPanel.setContinuousLayout(true);

		return codeViewPanel;
	}

	/**
	 * 下面是按钮面板的创建过程
	 * 
	 * @return
	 * 
	 * @since
	 */
	private JPanel createBtnPane() {
		btnPanel = new JPanel();
		returnButton = new JButton("返回");
		// 添加事件监听器
		returnButton.addActionListener(this);
		btnPanel.add(returnButton);

		saveButton = new JButton("保存代码");
		// 添加事件监听器
		saveButton.addActionListener(this);
		btnPanel.add(saveButton);
		return btnPanel;
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == saveButton) {
			String okMsg = "代码保存完成";
			if (genCodeMap != null && genCodeMap.size() > 0) {

				// copy base project to target folder
				if (codeDesc.isInitProject()) {
					if (!initProject()) {
						return;
					} else {
						okMsg = okMsg + ". 请执行"+ codeDesc.getProjectPath() + "\\init_project.bat";
					}
				}

				Iterator<String> it = genCodeMap.keySet().iterator();
				while (it.hasNext()) {
					String fileName = it.next();
					if (FileUtils.existFile(fileName)) {
						int rtn = JOptionPane.showConfirmDialog(this, "文件[" + fileName + "]已经存在，是否覆盖", "询问", 0);
						System.out.println(rtn);
						if (rtn == 1) {
							continue;
						}
					}
					try {
						System.out.println(fileName);
						FileUtils.saveFile(genCodeMap.get(fileName), fileName);
					} catch (IOException e1) {
						System.out.println(e1.getMessage());
					}
				}
			}
			JOptionPane.showMessageDialog(this, okMsg, "提示", -1);
		} else if (e.getSource() == returnButton) {
			this.dispose();
			frame.setVisible(true);
		}
	}

	@SuppressWarnings("null")
	private void initTree() {

		List<String> classNameList = this.codeDesc.getGenClassNameList();

		String diffStrWebPath = StrUtils.difference(codeDesc.getJavaPath(), codeDesc.getWebPath());
		String strProj = StrUtils.remove(codeDesc.getWebPath(), diffStrWebPath);
		String diffStrJavaPath = StrUtils.remove(codeDesc.getJavaPath(), strProj);

		// 创建项目目录tree
		String[] strProjTreeNode = strProj.replace("\\", "==").split("==");
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(strProjTreeNode[0]);
		DefaultMutableTreeNode treeNode = null;
		treeNode = root;
		for (int i = 1; i < strProjTreeNode.length; i++) {
			if (i == 1) {
				treeNode = createNode(root, strProjTreeNode[i].toString());
			} else {
				treeNode = createNode(treeNode.getFirstLeaf(), strProjTreeNode[i].toString());
			}
		}

		DefaultMutableTreeNode sameNode = treeNode.getFirstLeaf();

		// 添加java路径
		String[] strJavaTreeNode = diffStrJavaPath.replace("\\", "==").split("==");
		for (int i = 0; i < strJavaTreeNode.length; i++) {
			if (i == 0) {
				treeNode = createNode(sameNode, strJavaTreeNode[i].toString());
			} else {
				treeNode = createNode(sameNode.getLastLeaf(), strJavaTreeNode[i].toString());
			}
		}

		// add java file node
		DefaultMutableTreeNode lastLeaf = treeNode.getLastLeaf();
		DefaultMutableTreeNode lastNode = null;
		for (String clsName : classNameList) {
			System.out.println(clsName);
			if (clsName.endsWith(".java")) {
				if (clsName.contains("Entity.java")) {
					lastNode = new DefaultMutableTreeNode("entity");
				} else if (clsName.contains("Controller.java")) {
					lastNode = new DefaultMutableTreeNode("controller");
				} else if (clsName.contains("Service.java")) {
					lastNode = new DefaultMutableTreeNode("service");
				} else if (clsName.contains("Dao.java")) {
					lastNode = new DefaultMutableTreeNode("dao");
				}

				lastLeaf.add(lastNode);
				if (!StrUtils.isNull(codeDesc.getSubModuleName())) {
					DefaultMutableTreeNode lastNode2 = new DefaultMutableTreeNode(codeDesc.getSubModuleName());
					lastNode.add(lastNode2);

					lastNode2.add(new DefaultMutableTreeNode(clsName.substring(clsName.replace("\\", ":").lastIndexOf(
						":") + 1)));
				} else {
					lastNode.add(new DefaultMutableTreeNode(clsName.substring(clsName.replace("\\", ":").lastIndexOf(
						":") + 1)));
				}

			}
		}

		// 添加jsp路径
		String[] strWebTreeNode = diffStrWebPath.replace("\\", "==").split("==");
		for (int i = 0; i < strWebTreeNode.length; i++) {
			if (i == 0) {
				treeNode = createNode(sameNode, strWebTreeNode[i].toString());
			} else {
				treeNode = createNode(sameNode.getLastLeaf(), strWebTreeNode[i].toString());
			}
		}
		// add jsp file node
		lastLeaf = treeNode.getLastLeaf();
		for (String clsName : classNameList) {
			if (clsName.contains(".jsp")) {
				lastLeaf.add(new DefaultMutableTreeNode(clsName
					.substring(clsName.replace("\\", ":").lastIndexOf(":") + 1)));
			}
		}
		tree = new JTree(root);
		expandAll(tree, true);
	}

	private DefaultMutableTreeNode createNode(DefaultMutableTreeNode treeNode, String name) {
		DefaultMutableTreeNode leafNode = new DefaultMutableTreeNode(name);
		treeNode.add(leafNode);
		return treeNode;
	}

	public void expandAll(JTree tree, boolean expand) {
		TreeNode root = (TreeNode)tree.getModel().getRoot();
		// Traverse tree from root
		expandAll(tree, new TreePath(root), expand);
	}

	private void expandAll(JTree tree, TreePath parent, boolean expand) {
		// Traverse children
		TreeNode node = (TreeNode)parent.getLastPathComponent();
		if (node.getChildCount() >= 0) {
			for (Enumeration e = node.children(); e.hasMoreElements();) {
				TreeNode n = (TreeNode)e.nextElement();
				TreePath path = parent.pathByAddingChild(n);
				expandAll(tree, path, expand);
			}
		}
		// Expansion or collapse must be done bottom-up
		if (expand) {
			tree.expandPath(parent);
		} else {
			tree.collapsePath(parent);
		}
	}

	private boolean initProject() {
		String userDir = this.getClass().getClassLoader().getResource("").getPath();

		String projectPath = codeDesc.getProjectPath();
		if (Constants.PROJECT_TYPE_JAVA.equals(codeDesc.getProjType())) {
			// unzip src.zip to src path
			if (!ZipUtil.unZipFiles(userDir + Constants.BASIC_SRC_ZIP_FILE, projectPath)) {
				JOptionPane.showMessageDialog(this, "解压" + userDir + Constants.BASIC_SRC_ZIP_FILE + "到" + projectPath
					+ "出错", "Error", 0);
				return false;
			}

			// unzip webapp.zip to web path
			if (!ZipUtil.unZipFiles(userDir + Constants.BASIC_WEB_ZIP_FILE, projectPath)) {
				JOptionPane.showMessageDialog(this, "解压" + userDir + Constants.BASIC_WEB_ZIP_FILE + "到" + projectPath
					+ "出错", "Error", 0);
				return false;
			}
		} else if (Constants.PROJECT_TYPE_MAVEN.equals(codeDesc.getProjType())) {
			// unzip src.zip to src path
			if (!ZipUtil.unZipFiles(userDir + Constants.MAVEN_SRC_ZIP_FILE, projectPath)) {
				JOptionPane.showMessageDialog(this, "解压" + userDir + Constants.MAVEN_SRC_ZIP_FILE + "到" + projectPath
					+ "出错", "Error", 0);
				return false;
			}

			// copy and modify pom.xml
			FileUtils.copyFile(userDir + Constants.MAVEN_POM_FILE, projectPath + "/pom.xml");

			// copy and execute init_project.bat
			FileUtils.copyFile(userDir + Constants.MAVEN_INIT_PROJECT_BAT_FILE, projectPath + "/init_project.bat");
			AppUtil.callCmd(projectPath + "/init_project.bat " + projectPath.substring(0, 2) + " " + projectPath);
			// Runtime.getRuntime().exec(projectPath+"/init_project.bat " + projectPath);
		}

		return true;
	}
}
